{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Moving through a physical experience\n",
    "## Some examples of IoT application that ping a digital twin\n",
    "\n",
    "This doc does not really teach anything new, but it will give us some exercise with the previous examples. We will need a more complicated model in future steps. \n",
    "* Adding more connections.\n",
    "* Making connections using ids. \n",
    "\n",
    "\n",
    "[This is the SDK repo on Github](https://github.com/Azure/azure-sdk-for-python/tree/4559e19e2f3146a49f1eba1706bb798071f4a1f5/sdk/digitaltwins/azure-digitaltwins-core)\n",
    "\n",
    "[Here is the doc on the query language](https://docs.microsoft.com/en-us/azure/digital-twins/concepts-query-language)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<azure.digitaltwins.core._digitaltwins_client.DigitalTwinsClient at 0x29140d99c08>"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from azure.identity import AzureCliCredential\n",
    "from azure.digitaltwins.core import DigitalTwinsClient\n",
    "\n",
    "# using yaml instead of \n",
    "import yaml\n",
    "import uuid\n",
    "\n",
    "# using altair instead of matplotlib for vizuals\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "\n",
    "# you will get this from the ADT resource at portal.azure.com\n",
    "your_digital_twin_url = \"home-test-twin.api.wcus.digitaltwins.azure.net\"\n",
    "\n",
    "azure_cli = AzureCliCredential()\n",
    "service_client = DigitalTwinsClient(\n",
    "    your_digital_twin_url, azure_cli)\n",
    "service_client"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "query_expression = \"SELECT * FROM digitaltwins t where IS_OF_MODEL('dtmi:billmanh:patron;1')\"\n",
    "query_result = service_client.query_twins(query_expression)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Note** the query object loves to drop values. To keep from making multiple queries, save the data somewhere. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "values = []\n",
    "for i in query_result:\n",
    "    values.append(i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_customers = pd.DataFrame([[i['$dtId'],i['satisfaction']] for i in values],\n",
    "                           columns=['id','satisfaction'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>id</th>\n",
       "      <th>satisfaction</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>customer-cc04f3b6-39b0-4cef-bfff-a7d668cce446</td>\n",
       "      <td>10</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>customer-3cbd5e60-957d-44ff-944f-9adb42a20a52</td>\n",
       "      <td>10</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>customer-5c454e2f-f70b-4352-b75a-958f1a49beba</td>\n",
       "      <td>7</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>customer-26196fee-5ffd-457a-86b7-192a998f3cf2</td>\n",
       "      <td>9</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>customer-e6f49d8a-711b-41c3-9db8-c7ece3dbc32c</td>\n",
       "      <td>7</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>79</th>\n",
       "      <td>customer-45e9aa03-733d-4a99-b9d5-94f1c6b04214</td>\n",
       "      <td>9</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>80</th>\n",
       "      <td>customer-0234cb48-1fa2-43e0-b69d-36a6ff269666</td>\n",
       "      <td>9</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>81</th>\n",
       "      <td>customer-75b2f757-faee-4a85-bc93-e6e9ff7cd891</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>82</th>\n",
       "      <td>customer-048f85a8-173e-4305-92b8-ead2a748b07f</td>\n",
       "      <td>8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>83</th>\n",
       "      <td>customer-25e19268-3433-4f09-afe3-94f466313368</td>\n",
       "      <td>10</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>84 rows × 2 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                                               id  satisfaction\n",
       "0   customer-cc04f3b6-39b0-4cef-bfff-a7d668cce446            10\n",
       "1   customer-3cbd5e60-957d-44ff-944f-9adb42a20a52            10\n",
       "2   customer-5c454e2f-f70b-4352-b75a-958f1a49beba             7\n",
       "3   customer-26196fee-5ffd-457a-86b7-192a998f3cf2             9\n",
       "4   customer-e6f49d8a-711b-41c3-9db8-c7ece3dbc32c             7\n",
       "..                                            ...           ...\n",
       "79  customer-45e9aa03-733d-4a99-b9d5-94f1c6b04214             9\n",
       "80  customer-0234cb48-1fa2-43e0-b69d-36a6ff269666             9\n",
       "81  customer-75b2f757-faee-4a85-bc93-e6e9ff7cd891             6\n",
       "82  customer-048f85a8-173e-4305-92b8-ead2a748b07f             8\n",
       "83  customer-25e19268-3433-4f09-afe3-94f466313368            10\n",
       "\n",
       "[84 rows x 2 columns]"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_customers"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "and a `df` of the tickets"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>$dtId</th>\n",
       "      <th>event_title</th>\n",
       "      <th>state</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>ticket-633f4537-50a1-4735-9e70-99bf19be51e4</td>\n",
       "      <td>Smashing Pumpkins</td>\n",
       "      <td>open</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>ticket-52e25a0a-06b1-428f-b6a2-479cafc45c16</td>\n",
       "      <td>Smashing Pumpkins</td>\n",
       "      <td>open</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>ticket-0cd531c6-d81c-4c4c-84c9-9592a8f43e70</td>\n",
       "      <td>Foo Fighters</td>\n",
       "      <td>open</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>ticket-58bf00bf-d5b8-4d06-9002-f8bf1693cc56</td>\n",
       "      <td>Foo Fighters</td>\n",
       "      <td>open</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>ticket-67f3cbfb-4b35-4e10-bf6d-3fd216093c3c</td>\n",
       "      <td>Foo Fighters</td>\n",
       "      <td>open</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>ticket-3f82286d-7e0b-4df5-a491-d9e28f7c94f9</td>\n",
       "      <td>Foo Fighters</td>\n",
       "      <td>open</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                         $dtId        event_title state\n",
       "0  ticket-633f4537-50a1-4735-9e70-99bf19be51e4  Smashing Pumpkins  open\n",
       "1  ticket-52e25a0a-06b1-428f-b6a2-479cafc45c16  Smashing Pumpkins  open\n",
       "2  ticket-0cd531c6-d81c-4c4c-84c9-9592a8f43e70       Foo Fighters  open\n",
       "3  ticket-58bf00bf-d5b8-4d06-9002-f8bf1693cc56       Foo Fighters  open\n",
       "4  ticket-67f3cbfb-4b35-4e10-bf6d-3fd216093c3c       Foo Fighters  open\n",
       "5  ticket-3f82286d-7e0b-4df5-a491-d9e28f7c94f9       Foo Fighters  open"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "query_expression = f\"\"\"\n",
    "SELECT * FROM digitaltwins t where IS_OF_MODEL('dtmi:mymodels:ticket;1') and t.state='open'\n",
    "\"\"\"\n",
    "query_result = service_client.query_twins(query_expression)\n",
    "available_tickets_df = pd.DataFrame([[i['$dtId'],i['event_title'],i['state']] for i in query_result],\n",
    "                                   columns = ['$dtId','event_title','state'])\n",
    "available_tickets_df"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's sell a couple more of those tickets. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['ticket-633f4537-50a1-4735-9e70-99bf19be51e4',\n",
       " 'ticket-0cd531c6-d81c-4c4c-84c9-9592a8f43e70']"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tickets_sold = available_tickets_df.drop_duplicates(subset='event_title')['$dtId'].tolist()\n",
    "\n",
    "tickets_sold"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['customer-c87adbfa-1c6e-4ea9-9f03-83e3877ef5fc',\n",
       " 'customer-21e17d28-76c3-4c04-8df9-396703692a68']"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "customers_sold = df_customers['id'].tolist()[5:7]\n",
    "\n",
    "customers_sold"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The purpose is to create a simulation. So I'm just hacking something out real quick to make our model look a little fuller."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ticket-633f4537-50a1-4735-9e70-99bf19be51e4\n",
      "ticket-0cd531c6-d81c-4c4c-84c9-9592a8f43e70\n"
     ]
    }
   ],
   "source": [
    "for c,t in enumerate(tickets_sold):\n",
    "    print(t)\n",
    "    tickethoder_relationship = {\n",
    "            \"$relationshipId\": f\"{t}ownedBy{customers_sold[c]}\",\n",
    "            \"$sourceId\": t,\n",
    "            \"$relationshipName\": \"ownedBy\",\n",
    "            \"$targetId\": customers_sold[c],\n",
    "            \"bought_online\": False\n",
    "        }\n",
    "\n",
    "    service_client.upsert_relationship(\n",
    "            tickethoder_relationship[\"$sourceId\"],\n",
    "            tickethoder_relationship[\"$relationshipId\"],\n",
    "            tickethoder_relationship\n",
    "        )\n",
    "\n",
    "    patch = [\n",
    "        {\n",
    "            \"op\": \"replace\",\n",
    "            \"path\": \"\",\n",
    "            \"value\": \"sold\"\n",
    "        }\n",
    "    ]\n",
    "    service_client.update_component(t,\"state\", patch)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You should be able to load the storage explorer at this point and look at the relationships. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "I'm going to add some areas. \n",
    "* People go into areas when the concert begins.\n",
    "* areas have capacity\n",
    "\n",
    "Also adding lines:\n",
    "* Lines lead to other places, but one line can lead to many places (like the entrance).\n",
    "* Lines have a capacity\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "metadata": {},
   "outputs": [],
   "source": [
    "# # # Delete the model that you don't want. \n",
    "# # service_client.delete_model(patron_model_id)\n",
    "\n",
    "# # Create it if you just deleted it.\n",
    "# # area_model_json = yaml.safe_load(open(\"models/area.json\"))\n",
    "# line_model_json = yaml.safe_load(open(\"models/Patron.json\"))\n",
    "# service_client.create_models([line_model_json])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ok now that we know what tickets we want to sell, let's push them to the digital twin ecosystem. This is exactly the same as what we did with `Customers` in step one. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "area-0\n",
      "{'$dtId': 'area-0', '$etag': 'W/\"7789a5c1-8ab0-473d-9c0e-6c12abe8f20f\"', 'capacity': 3, 'status': 'open', '$metadata': {'$model': 'dtmi:billmanh:area;1', 'capacity': {'lastUpdateTime': '2020-11-29T23:47:16.3097488Z'}, 'status': {'lastUpdateTime': '2020-11-29T23:47:16.3097488Z'}}}\n",
      "area-1\n",
      "{'$dtId': 'area-1', '$etag': 'W/\"78d4f941-5c4f-4e55-9a24-e1061f35a0f9\"', 'capacity': 3, 'status': 'open', '$metadata': {'$model': 'dtmi:billmanh:area;1', 'capacity': {'lastUpdateTime': '2020-11-29T23:47:16.3994079Z'}, 'status': {'lastUpdateTime': '2020-11-29T23:47:16.3994079Z'}}}\n",
      "area-2\n",
      "{'$dtId': 'area-2', '$etag': 'W/\"8d9d633f-51e1-4814-bf7f-71ffa5b647e6\"', 'capacity': 3, 'status': 'open', '$metadata': {'$model': 'dtmi:billmanh:area;1', 'capacity': {'lastUpdateTime': '2020-11-29T23:47:16.4841446Z'}, 'status': {'lastUpdateTime': '2020-11-29T23:47:16.4841446Z'}}}\n",
      "area-3\n",
      "{'$dtId': 'area-3', '$etag': 'W/\"990a5327-b8e5-4051-9ce2-9a078ec3c0aa\"', 'capacity': 3, 'status': 'open', '$metadata': {'$model': 'dtmi:billmanh:area;1', 'capacity': {'lastUpdateTime': '2020-11-29T23:47:16.5562464Z'}, 'status': {'lastUpdateTime': '2020-11-29T23:47:16.5562464Z'}}}\n"
     ]
    }
   ],
   "source": [
    "for r in range(4):\n",
    "    digital_twin_id = f'area-{r}'\n",
    "    print(digital_twin_id)\n",
    "    dt_json = {\n",
    "        \"$metadata\": {\n",
    "            \"$model\": \"dtmi:mymodels:area;1\"\n",
    "        },\n",
    "        \"capacity\": 3,\n",
    "        \"status\": \"open\"\n",
    "    }\n",
    "    created_twin = service_client.upsert_digital_twin(digital_twin_id, dt_json)\n",
    "    print(created_twin)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "line-0\n",
      "{'$dtId': 'line-0', '$etag': 'W/\"efd0563b-244c-41b1-8a02-7d2f5bcb11cb\"', '$metadata': {'$model': 'dtmi:billmanh:line;1'}}\n",
      "line-1\n",
      "{'$dtId': 'line-1', '$etag': 'W/\"e96e3bcb-3829-4fd0-a042-6d5f866fbd0a\"', '$metadata': {'$model': 'dtmi:billmanh:line;1'}}\n",
      "line-2\n",
      "{'$dtId': 'line-2', '$etag': 'W/\"c2f75074-3491-47b4-a703-6ade5e9993ad\"', '$metadata': {'$model': 'dtmi:billmanh:line;1'}}\n",
      "line-3\n",
      "{'$dtId': 'line-3', '$etag': 'W/\"8d749fc0-c15f-448d-b246-8f2d9212a29d\"', '$metadata': {'$model': 'dtmi:billmanh:line;1'}}\n"
     ]
    }
   ],
   "source": [
    "for r in range(4):\n",
    "    digital_twin_id = f'line-{r}'\n",
    "    print(digital_twin_id)\n",
    "    dt_json = {\n",
    "        \"$metadata\": {\n",
    "            \"$model\": \"dtmi:mymodels:line;1\"\n",
    "        }\n",
    "    }\n",
    "    created_twin = service_client.upsert_digital_twin(digital_twin_id, dt_json)\n",
    "    print(created_twin)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now establishing a realtionship between the lines and the areas. If a person leaves one area they have to get into the line of the next area in order to get there. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {},
   "outputs": [],
   "source": [
    "def line_to_room(line,area,walking):\n",
    "    tickethoder_relationship = {\n",
    "                \"$relationshipId\": f\"{line}leadsTo{area}\",\n",
    "                \"$sourceId\": line,\n",
    "                \"$relationshipName\": \"leadsTo\",\n",
    "                \"$targetId\": area,\n",
    "                \"walk_distance\": walking\n",
    "            }\n",
    "\n",
    "    service_client.upsert_relationship(\n",
    "            tickethoder_relationship[\"$sourceId\"],\n",
    "            tickethoder_relationship[\"$relationshipId\"],\n",
    "            tickethoder_relationship\n",
    "        )\n",
    "        \n",
    "line_to_room(\"line-0\",\"area-0\",5)\n",
    "line_to_room(\"line-1\",\"area-1\",5)\n",
    "line_to_room(\"line-2\",\"area-2\",5)\n",
    "line_to_room(\"line-3\",\"area-3\",5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now I'm going to add some people into different parts of the experience. This will change from user to user, but you can use this as an example of how this would work on your twin. Use the queries above to get the specific ids of your twins."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {},
   "outputs": [],
   "source": [
    "def cust_to_area(cust,area):\n",
    "    tickethoder_relationship = {\n",
    "                \"$relationshipId\": f\"{cust}locatedIn{area}\",\n",
    "                \"$sourceId\": cust,\n",
    "                \"$relationshipName\": \"locatedIn\",\n",
    "                \"$targetId\": area,\n",
    "            }\n",
    "\n",
    "    service_client.upsert_relationship(\n",
    "            tickethoder_relationship[\"$sourceId\"],\n",
    "            tickethoder_relationship[\"$relationshipId\"],\n",
    "            tickethoder_relationship\n",
    "        )\n",
    "        \n",
    "cust_to_area(\"customer-e6f49d8a-711b-41c3-9db8-c7ece3dbc32c\",\"line-1\")\n",
    "cust_to_area(\"customer-21e17d28-76c3-4c04-8df9-396703692a68\",\"line-1\")\n",
    "# cust_to_area(\"customer-25e19268-3433-4f09-afe3-94f466313368\",\"line-0\")\n",
    "# cust_to_area(\"customer-c87adbfa-1c6e-4ea9-9f03-83e3877ef5fc\",\"line-2\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Sell a couple more tickets"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {},
   "outputs": [],
   "source": [
    "def ticket_to_cust(ticket,cust):\n",
    "    tickethoder_relationship = {\n",
    "                \"$relationshipId\": f\"{ticket}ownedBy{cust}\",\n",
    "                \"$sourceId\": ticket,\n",
    "                \"$relationshipName\": \"ownedBy\",\n",
    "                \"$targetId\": cust,\n",
    "            }\n",
    "\n",
    "    service_client.upsert_relationship(\n",
    "            tickethoder_relationship[\"$sourceId\"],\n",
    "            tickethoder_relationship[\"$relationshipId\"],\n",
    "            tickethoder_relationship\n",
    "        )\n",
    "        \n",
    "ticket_to_cust(\"ticket-58bf00bf-d5b8-4d06-9002-f8bf1693cc56\",\"customer-418cbc74-b101-4f50-8cf0-6075a2a8053c\")\n",
    "ticket_to_cust(\"ticket-67f3cbfb-4b35-4e10-bf6d-3fd216093c3c\",\"customer-9c9b5c36-69f6-4f48-9362-4aaac4cb1be4\")\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python (azure_test)",
   "language": "python",
   "name": "azure_test"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}